home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / POV-Ray 3.0.2 / src / SOURCE / OPTIN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-06-24  |  54.9 KB  |  2,432 lines  |  [TEXT/CWIE]

  1. /****************************************************************************
  2. *                   optin.c
  3. *
  4. *  This module contains functions for ini-file/command line parsing, streams.
  5. *
  6. *  from Persistence of Vision(tm) Ray Tracer
  7. *  Copyright 1996 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. *  NOTICE: This source code file is provided so that users may experiment
  10. *  with enhancements to POV-Ray and to port the software to platforms other
  11. *  than those supported by the POV-Ray Team.  There are strict rules under
  12. *  which you are permitted to use this file.  The rules are in the file
  13. *  named POVLEGAL.DOC which should be distributed with this file. If
  14. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  15. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  16. *  Forum.  The latest version of POV-Ray may be found there as well.
  17. *
  18. * This program is based on the popular DKB raytracer version 2.12.
  19. * DKBTrace was originally written by David K. Buck.
  20. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  21. *
  22. *****************************************************************************/
  23.  
  24. /****************************************************************************
  25. *
  26. *  This file contains the routines to implement an .INI file parser that can
  27. *  parse options in the form "Variable=value" or traditional POV-Ray
  28. *  command-line switches.  Values can come from POVRAYOPT, command-line,
  29. *  .DEF or .INI files.
  30. *
  31. *  Written by CEY 4/94 based on existing code and INI code from CDW.
  32. *
  33. *  ---
  34. *
  35. *****************************************************************************/
  36.  
  37. #include <ctype.h>
  38. #include <time.h>
  39. #include "frame.h"
  40. #include "povproto.h"
  41. #include "bbox.h"
  42. #include "lighting.h"
  43. #include "mem.h"        /*POV_FREE*/
  44. #include "octree.h"
  45. #include "povray.h"
  46. #include "optin.h"
  47. #include "optout.h"
  48. #include "parse.h"
  49. #include "radiosit.h"
  50. #include "render.h"
  51. #include "tokenize.h"
  52. #include "vlbuffer.h"
  53. #include "ppm.h"
  54. #include "targa.h"
  55. #include "userio.h"
  56. #include "png_pov.h"
  57.  
  58.  
  59.  
  60. /*****************************************************************************
  61. * Local preprocessor defines
  62. ******************************************************************************/
  63.  
  64.  
  65. /*****************************************************************************
  66. * Local typedefs
  67. ******************************************************************************/
  68.  
  69.  
  70.  
  71. /*****************************************************************************
  72. * Local variables
  73. ******************************************************************************/
  74.  
  75. char *DefaultFile[] =
  76. {
  77.   "debug.out",
  78.   "fatal.out",
  79.   "render.out",
  80.   "stats.out",
  81.   "warning.out",
  82.   "alltext.out"
  83. };
  84.  
  85. int inflag, outflag;
  86.  
  87. /* Quality constants */
  88.  
  89. long Quality_Values[12]=
  90. {
  91.   QUALITY_0, QUALITY_1, QUALITY_2, QUALITY_3, QUALITY_4,
  92.   QUALITY_5, QUALITY_6, QUALITY_7, QUALITY_8, QUALITY_9
  93. };
  94.  
  95. /* Keywords for the ini-file parser. */
  96.  
  97. struct Reserved_Word_Struct Option_Variable [] =
  98. {
  99.   { ALL_CONSOLE_OP, "All_Console" },
  100.   { ALL_FILE_OP, "All_File" },
  101.   { ANTIALIAS_DEPTH_OP, "Antialias_Depth" },
  102.   { ANTIALIAS_OP, "Antialias" },
  103.   { ANTIALIAS_THRESH_OP, "Antialias_Threshold" },
  104.   { BOUNDING_OP, "Bounding" },
  105.   { BOUNDING_THRESH_OP, "Bounding_Threshold" },
  106.   { BUFFERED_OUTPUT_OP,"Buffer_Output" },
  107.   { BUF_SIZE_OP, "Buffer_Size" },
  108.   { CLOCK_OP, "Clock" },
  109.  
  110.   { CONTINUE_OP, "Continue_Trace" },
  111.   { CREATE_INI_OP, "Create_Ini" },
  112.   { CYCLIC_ANIMATION_OP, "Cyclic_Animation" },
  113.   { DEBUG_CONSOLE_OP, "Debug_Console" },
  114.   { DEBUG_FILE_OP, "Debug_File" },
  115.   { DISPLAY_OP, "Display" },
  116.   { DISPLAY_GAMMA_OP, "Display_Gamma" },
  117.   { DRAW_VISTAS_OP, "Draw_Vistas" },
  118.   { END_COLUMN_OP, "End_Column" },
  119.   { END_ROW_OP, "End_Row" },
  120.   { FATAL_CONSOLE_OP, "Fatal_Console" },
  121.  
  122.   { FATAL_ERROR_CMD_OP, "Fatal_Error_Command" },
  123.   { FATAL_ERROR_RET_OP, "Fatal_Error_Return" },
  124.   { FATAL_FILE_OP, "Fatal_File" },
  125.   { FIELD_RENDER_OP, "Field_Render" },
  126.   { FILE_OUTPUT_OP, "Output_to_File" },
  127.   { FILE_OUTPUT_TYPE_OP, "Output_File_Type" },
  128.   { FINAL_CLOCK_OP, "Final_Clock" },
  129.   { FINAL_FRAME_OP, "Final_Frame" },
  130.   { HEIGHT_OP, "Height" },
  131.   { HIST_NAME_OP, "Histogram_Name" },
  132.  
  133.   { HIST_SIZE_OP, "Histogram_Grid_Size" },
  134.   { HIST_TYPE_OP, "Histogram_Type" },
  135.   { INITIAL_CLOCK_OP, "Initial_Clock" },
  136.   { INITIAL_FRAME_OP, "Initial_Frame" },
  137.   { INPUT_FILE_NAME_OP, "Input_File_Name" },
  138.   { JITTER_AMOUNT_OP, "Jitter_Amount" },
  139.   { JITTER_OP, "Jitter" },
  140.   { LIBRARY_PATH_OP, "Library_Path" },
  141.   { LIGHT_BUFFER_OP, "Light_Buffer" },
  142.   { ODD_FIELD_OP, "Odd_Field" },
  143.  
  144.   { OUTPUT_ALPHA_OP, "Output_Alpha" },
  145.   { OUTPUT_FILE_NAME_OP, "Output_File_Name" },
  146.   { PALETTE_OP, "Palette" },
  147.   { PAUSE_WHEN_DONE_OP, "Pause_When_Done" },
  148.   { POST_FRAME_CMD_OP, "Post_Frame_Command" },
  149.   { POST_FRAME_RET_OP, "Post_Frame_Return" },
  150.   { POST_SCENE_CMD_OP, "Post_Scene_Command" },
  151.   { POST_SCENE_RET_OP, "Post_Scene_Return" },
  152.   { PREVIEW_E_OP, "Preview_End_Size" },
  153.   { PREVIEW_S_OP, "Preview_Start_Size" },
  154.  
  155.   { PRE_FRAME_CMD_OP, "Pre_Frame_Command" },
  156.   { PRE_FRAME_RET_OP, "Pre_Frame_Return" },
  157.   { PRE_SCENE_CMD_OP, "Pre_Scene_command" },
  158.   { PRE_SCENE_RET_OP, "Pre_Scene_Return" },
  159.   { QUALITY_OP, "Quality" },
  160.   { RAD_SWITCH_OP, "Radiosity" },
  161.   { REMOVE_BOUNDS_OP, "Remove_Bounds" },
  162.   { RENDER_CONSOLE_OP, "Render_Console" },
  163.   { RENDER_FILE_OP, "Render_File" },
  164.   { SAMPLING_METHOD_OP, "Sampling_Method" },
  165.  
  166.   { SPLIT_UNIONS_OP, "Split_Unions" },
  167.   { START_COLUMN_OP, "Start_Column" },
  168.   { START_ROW_OP, "Start_Row" },
  169.   { STATISTIC_CONSOLE_OP, "Statistic_Console" },
  170.   { STATISTIC_FILE_OP, "Statistic_File" },
  171.   { SUBSET_END_FRAME_OP, "Subset_End_Frame" },
  172.   { SUBSET_START_FRAME_OP, "Subset_Start_Frame" },
  173.   { TEST_ABORT_COUNT_OP, "Test_Abort_Count" },
  174.   { TEST_ABORT_OP, "Test_Abort" },
  175.   { USER_ABORT_CMD_OP, "User_Abort_Command" },
  176.  
  177.   { USER_ABORT_RET_OP, "User_Abort_Return" },
  178.   { VERBOSE_OP, "Verbose" },
  179.   { VERSION_OP, "Version" },
  180.   { VIDEO_MODE_OP, "Video_Mode" },
  181.   { VISTA_BUFFER_OP, "Vista_Buffer" },
  182.   { WARNING_CONSOLE_OP, "Warning_Console" },
  183.   { WARNING_FILE_OP, "Warning_File" },
  184.   { WIDTH_OP, "Width" },
  185.  
  186.   { BITS_PER_COLOR_OP, "Bits_Per_Color" },
  187.   { BITS_PER_COLOUR_OP, "Bits_Per_Colour" },
  188.   { INCLUDE_INI_OP, "Include_Ini" }
  189. };
  190.  
  191. static char temp_string[3]="\0\0";
  192. static char ret_string[7]="IQUFSA";
  193.  
  194. /*****************************************************************************
  195. * static functions
  196. ******************************************************************************/
  197.  
  198. static int matches PARAMS(( char *v1, char *v2 ));
  199. static int istrue PARAMS(( char *value ));
  200. static int isfalse PARAMS(( char *value ));
  201.  
  202. /*****************************************************************************
  203. *
  204. * FUNCTION
  205. *
  206. *   get_ini_value
  207. *
  208. * INPUT
  209. *
  210. *   op - the .ini option's index
  211. *   libind - if op = LIBRARY_PATH_OP, the library's index
  212. *   
  213. * OUTPUT
  214. *   
  215. * RETURNS
  216. *
  217. *   char * pointing to a static string representation of the
  218. *   option's value.
  219. *   
  220. * AUTHOR
  221. *
  222. *   SCD, 2/95
  223. *   
  224. * DESCRIPTION
  225. *
  226. *   Returns a static string representation of an option's value.
  227. *
  228. * CHANGES
  229. *
  230. *   -
  231. *
  232. ******************************************************************************/
  233.  
  234. char *get_ini_value(op, libind)
  235. int op, libind;
  236. {
  237.   static char value[128];
  238.  
  239.   value[0] = '\0';
  240.  
  241.   switch (op)
  242.   {
  243.     case BUF_SIZE_OP:
  244.       sprintf(value,"%d", opts.File_Buffer_Size>>10);
  245.       return(value);
  246.  
  247.     case BUFFERED_OUTPUT_OP:
  248.       return (opts.Options & BUFFERED_OUTPUT ? "On" : "Off");
  249.  
  250.     case CONTINUE_OP:
  251.       return (opts.Options & CONTINUE_TRACE ? "On" : "Off");
  252.  
  253.     case DISPLAY_OP:
  254.       return (opts.Options & DISPLAY ? "On" : "Off");
  255.  
  256.     case VIDEO_MODE_OP:
  257.       sprintf(value,"%c",opts.DisplayFormat);
  258.       return(value);
  259.  
  260.     case PALETTE_OP:
  261.       sprintf(value,"%c",opts.PaletteOption);
  262.       return(value);
  263.  
  264.     case VERBOSE_OP:
  265.       return (opts.Options & VERBOSE ? "On" : "Off");
  266.  
  267.     case WIDTH_OP:
  268.       sprintf(value,"%d",Frame.Screen_Width);
  269.       return(value);
  270.  
  271.     case HEIGHT_OP:
  272.       sprintf(value,"%d",Frame.Screen_Height);
  273.       return(value);
  274.  
  275.     case FILE_OUTPUT_OP:
  276.       return (opts.Options & DISKWRITE ? "On" : "Off");
  277.  
  278.     case FILE_OUTPUT_TYPE_OP:
  279.       sprintf(value,"%c",opts.OutputFormat);
  280.       return(value);
  281.  
  282.     case PAUSE_WHEN_DONE_OP:
  283.       return (opts.Options & PROMPTEXIT ? "On" : "Off");
  284.  
  285.     case INPUT_FILE_NAME_OP:
  286.       return opts.Input_File_Name;
  287.  
  288.     case OUTPUT_FILE_NAME_OP:
  289.       return opts.Output_File_Name;
  290.  
  291.     case ANTIALIAS_OP:
  292.       return (opts.Options & ANTIALIAS ? "On" : "Off");
  293.  
  294.     case ANTIALIAS_THRESH_OP:
  295.       sprintf(value,"%g",opts.Antialias_Threshold);
  296.       return(value);
  297.  
  298.     case ANTIALIAS_DEPTH_OP:
  299.       sprintf(value,"%ld",opts.AntialiasDepth);
  300.       return(value);
  301.  
  302.     case JITTER_OP:
  303.       return (opts.Options & JITTER ? "On" : "Off");
  304.  
  305.     case JITTER_AMOUNT_OP:
  306.       sprintf(value,"%g",opts.JitterScale);
  307.       return(value);
  308.  
  309.     case TEST_ABORT_OP:
  310.       return (opts.Options & EXITENABLE ? "On" : "Off");
  311.  
  312.     case TEST_ABORT_COUNT_OP:
  313.       sprintf(value,"%d",opts.Abort_Test_Counter);
  314.       return(value);
  315.  
  316.     case LIBRARY_PATH_OP:
  317.       return opts.Library_Paths[libind];
  318.  
  319.     case START_COLUMN_OP:
  320.       if (opts.First_Column == -1)
  321.         sprintf(value,"%g",opts.First_Column_Percent);
  322.       else
  323.         sprintf(value,"%d",opts.First_Column);
  324.       return(value);
  325.  
  326.     case START_ROW_OP:
  327.       if (opts.First_Line == -1)
  328.         sprintf(value,"%g",opts.First_Line_Percent);
  329.       else
  330.         sprintf(value,"%d",opts.First_Line);
  331.       return(value);
  332.  
  333.     case END_COLUMN_OP:
  334.       if (opts.Last_Column == -1)
  335.         sprintf(value,"%g",opts.Last_Column_Percent);
  336.       else
  337.         sprintf(value,"%d",opts.Last_Column);
  338.       return(value);
  339.  
  340.     case END_ROW_OP:
  341.       if (opts.Last_Line == -1)
  342.         sprintf(value,"%g",opts.Last_Line_Percent);
  343.       else
  344.         sprintf(value,"%d",opts.Last_Line);
  345.       return(value);
  346.  
  347.     case VERSION_OP:
  348.       sprintf(value,"%g",opts.Language_Version);
  349.       return(value);
  350.  
  351.     case BOUNDING_OP:
  352.       return (opts.Use_Slabs ? "On" : "Off");
  353.  
  354.     case BOUNDING_THRESH_OP:
  355.       sprintf(value,"%ld",opts.BBox_Threshold);
  356.       return(value);
  357.  
  358.     case QUALITY_OP:
  359.       sprintf(value,"%d",opts.Quality);
  360.       return(value);
  361.  
  362.     case PREVIEW_S_OP:
  363.       sprintf(value,"%d",opts.PreviewGridSize_Start);
  364.       return value;
  365.  
  366.     case PREVIEW_E_OP:
  367.       sprintf(value,"%d",opts.PreviewGridSize_End);
  368.       return value;
  369.  
  370.     case CLOCK_OP:
  371.       sprintf(value,"%g",opts.FrameSeq.Clock_Value);
  372.       return value;
  373.  
  374.     case INITIAL_FRAME_OP:
  375.       sprintf(value,"%d",opts.FrameSeq.InitialFrame);
  376.       return value;
  377.  
  378.     case INITIAL_CLOCK_OP:
  379.       sprintf(value,"%g",opts.FrameSeq.InitialClock);
  380.       return value;
  381.  
  382.     case FINAL_FRAME_OP:
  383.       sprintf(value,"%d",opts.FrameSeq.FinalFrame);
  384.       return value;
  385.  
  386.     case FINAL_CLOCK_OP:
  387.       sprintf(value,"%g",opts.FrameSeq.FinalClock);
  388.       return value;
  389.  
  390.     case SUBSET_START_FRAME_OP:
  391.       sprintf(value,"%d",opts.FrameSeq.SubsetStartFrame);
  392.       return value;
  393.  
  394.     case SUBSET_END_FRAME_OP:
  395.       sprintf(value,"%d",opts.FrameSeq.SubsetEndFrame);
  396.       return value;
  397.  
  398.     case CREATE_INI_OP:
  399.       return opts.Ini_Output_File_Name;
  400.  
  401.     case ALL_CONSOLE_OP:
  402.       return (Stream_Info[ALL_STREAM].do_console ? "On" : "Off");
  403.  
  404.     case ALL_FILE_OP:
  405.       return (Stream_Info[ALL_STREAM].name ? Stream_Info[ALL_STREAM].name : "");
  406.  
  407.     case DEBUG_CONSOLE_OP:
  408.       return (Stream_Info[DEBUG_STREAM].do_console ? "On" : "Off");
  409.  
  410.     case DEBUG_FILE_OP:
  411.       return (Stream_Info[DEBUG_STREAM].name ? Stream_Info[DEBUG_STREAM].name : "");
  412.  
  413.     case RENDER_CONSOLE_OP:
  414.       return (Stream_Info[RENDER_STREAM].do_console ? "On" : "Off");
  415.  
  416.     case RENDER_FILE_OP:
  417.       return (Stream_Info[RENDER_STREAM].name ? Stream_Info[RENDER_STREAM].name : "");
  418.  
  419.     case STATISTIC_CONSOLE_OP:
  420.       return (Stream_Info[STATISTIC_STREAM].do_console ? "On" : "Off");
  421.  
  422.     case STATISTIC_FILE_OP:
  423.       return (Stream_Info[STATISTIC_STREAM].name ? Stream_Info[STATISTIC_STREAM].name : "");
  424.  
  425.     case WARNING_CONSOLE_OP:
  426.       return (Stream_Info[WARNING_STREAM].do_console ? "On" : "Off");
  427.  
  428.     case WARNING_FILE_OP:
  429.       return (Stream_Info[WARNING_STREAM].name ? Stream_Info[WARNING_STREAM].name : "");
  430.  
  431.     case FATAL_CONSOLE_OP:
  432.       return (Stream_Info[FATAL_STREAM].do_console ? "On" : "Off");
  433.  
  434.     case FATAL_FILE_OP:
  435.       return (Stream_Info[FATAL_STREAM].name ? Stream_Info[FATAL_STREAM].name : "");
  436.  
  437.     case RAD_SWITCH_OP:
  438.       return (opts.Options & RADIOSITY ? "On" : "Off");
  439.  
  440.     case HIST_SIZE_OP:
  441.       sprintf (value, "%d.%d", opts.histogram_x, opts.histogram_y) ;
  442.       return (value) ;
  443.  
  444.     case HIST_TYPE_OP:
  445.       switch (opts.histogram_type)
  446.       {
  447.         case CSV :
  448.           return ("C ; CSV") ;
  449.  
  450.         case SYS :
  451.           return ("S ; SYS") ;
  452.  
  453.         case PPM :
  454.           return ("P ; PPM") ;
  455.  
  456.         case TARGA :
  457.           return ("T ; TARGA") ;
  458.  
  459.         case PNG :
  460.           return ("N ; PNG") ;
  461.  
  462.         case NONE :
  463.           return ("X ; NONE") ;
  464.  
  465.       }
  466.       return ("X ; [UNKNOWN VALUE PASSED]") ;
  467.  
  468.     case HIST_NAME_OP:
  469.       return (opts.Histogram_File_Name) ;
  470.  
  471.     case VISTA_BUFFER_OP:
  472.       return ((opts.Options & USE_VISTA_BUFFER) ? "On" : "Off");
  473.  
  474.     case LIGHT_BUFFER_OP:
  475.       return ((opts.Options & USE_LIGHT_BUFFER) ? "On" : "Off");
  476.  
  477.     case DRAW_VISTAS_OP:
  478.       return ((opts.Options & USE_VISTA_DRAW) ? "On" : "Off");
  479.  
  480.     case SPLIT_UNIONS_OP:
  481.       return ((opts.Options & SPLIT_UNION) ? "On" : "Off");
  482.  
  483.     case REMOVE_BOUNDS_OP:
  484.       return ((opts.Options & REMOVE_BOUNDS) ? "On" : "Off");
  485.  
  486.     case CYCLIC_ANIMATION_OP:
  487.       return ((opts.Options & CYCLIC_ANIMATION) ? "On" : "Off");
  488.  
  489.     case PRE_SCENE_CMD_OP:
  490.       return opts.Shellouts[PRE_SCENE_SHL].Command;
  491.  
  492.     case PRE_FRAME_CMD_OP:
  493.       return opts.Shellouts[PRE_FRAME_SHL].Command;
  494.  
  495.     case POST_FRAME_CMD_OP:
  496.       return opts.Shellouts[POST_FRAME_SHL].Command;
  497.  
  498.     case POST_SCENE_CMD_OP:
  499.       return opts.Shellouts[POST_SCENE_SHL].Command;
  500.  
  501.     case USER_ABORT_CMD_OP:
  502.       return opts.Shellouts[USER_ABORT_SHL].Command;
  503.  
  504.     case FATAL_ERROR_CMD_OP:
  505.       return opts.Shellouts[FATAL_SHL].Command;
  506.  
  507.     case PRE_SCENE_RET_OP:
  508.       temp_string[0]=(opts.Shellouts[PRE_SCENE_SHL].Inverse)?'!':' ';
  509.       temp_string[1]=ret_string[opts.Shellouts[PRE_SCENE_SHL].Ret];
  510.       return temp_string;
  511.  
  512.     case PRE_FRAME_RET_OP:
  513.       temp_string[0]=(opts.Shellouts[PRE_FRAME_SHL].Inverse)?'!':' ';
  514.       temp_string[1]=ret_string[opts.Shellouts[PRE_FRAME_SHL].Ret];
  515.       return temp_string;
  516.  
  517.     case POST_FRAME_RET_OP:
  518.       temp_string[0]=(opts.Shellouts[POST_FRAME_SHL].Inverse)?'!':' ';
  519.       temp_string[1]=ret_string[opts.Shellouts[POST_FRAME_SHL].Ret];
  520.       return temp_string;
  521.  
  522.     case POST_SCENE_RET_OP:
  523.       temp_string[0]=(opts.Shellouts[POST_SCENE_SHL].Inverse)?'!':' ';
  524.       temp_string[1]=ret_string[opts.Shellouts[POST_SCENE_SHL].Ret];
  525.       return temp_string;
  526.  
  527.     case USER_ABORT_RET_OP:
  528.       temp_string[0]=(opts.Shellouts[USER_ABORT_SHL].Inverse)?'!':' ';
  529.       temp_string[1]=ret_string[opts.Shellouts[USER_ABORT_SHL].Ret];
  530.       return temp_string;
  531.  
  532.     case FATAL_ERROR_RET_OP:
  533.       temp_string[0]=(opts.Shellouts[FATAL_SHL].Inverse)?'!':' ';
  534.       temp_string[1]=ret_string[opts.Shellouts[FATAL_SHL].Ret];
  535.       return temp_string;
  536.  
  537.     case OUTPUT_ALPHA_OP:
  538.       return ((opts.Options & OUTPUT_ALPHA) ? "On" : "Off");
  539.  
  540.     case FIELD_RENDER_OP:
  541.       return (opts.FrameSeq.Field_Render_Flag ? "On" : "Off");
  542.  
  543.     case ODD_FIELD_OP:
  544.       return (opts.FrameSeq.Odd_Field_Flag ? "On" : "Off");
  545.       
  546.     case SAMPLING_METHOD_OP:
  547.       sprintf(value,"%d",opts.Tracing_Method);
  548.       return value;
  549.  
  550.     case BITS_PER_COLOR_OP:
  551.     case BITS_PER_COLOUR_OP:
  552.       sprintf(value,"%d",opts.OutputQuality);
  553.       return value;
  554.  
  555.     case DISPLAY_GAMMA_OP:
  556.       sprintf(value,"%g",opts.DisplayGamma);
  557.       return value;
  558.  
  559.     case INCLUDE_INI_OP:
  560.       value[0] = '\0';
  561.       return value;
  562.  
  563.     default:
  564.       Error("Unknown INI option in Write_INI.");
  565.   }
  566.  
  567.   return(value);
  568. }
  569.  
  570.  
  571.  
  572. /*****************************************************************************
  573. *
  574. * FUNCTION
  575. *
  576. *   parse_switch
  577. *
  578. * INPUT
  579. *   
  580. * OUTPUT
  581. *   
  582. * RETURNS
  583. *   
  584. * AUTHOR
  585. *
  586. *   POV-Ray Team
  587. *   
  588. * DESCRIPTION
  589. *
  590. *   Parses a traditional POV-Ray command-line switch that starts
  591. *   with + or -.  Whenever it seemed feasible, calls process_variable
  592. *   to perform the function rather than doing so itself.  Although this
  593. *   requires another pass through a switch{case, case...}, it insures
  594. *   that command-line switches and variable=value options get treated
  595. *   identically.
  596. *
  597. * CHANGES
  598. *
  599. *   -
  600. *
  601. *   Sep 1994 : Added options for union splitting, vista/light buffer. [DB]
  602. *   Jan 1995 : Added options for histogram grid. [CJC]
  603. *   Feb 1995 : Added options for console/file redirection and .INI writing [SCD]
  604. *
  605. ******************************************************************************/
  606.  
  607. void parse_switch (Option_String)
  608. char *Option_String;
  609. {
  610.   int i;
  611.   unsigned long Add_Option;
  612.   unsigned long Option_Number;
  613.   long longval;
  614.   DBL floatval;
  615.  
  616.   if (*(Option_String++) == '-')
  617.   {
  618.     Add_Option = FALSE;
  619.   }
  620.   else
  621.   {
  622.     Add_Option = TRUE;
  623.   }
  624.  
  625.   Option_Number = 0;
  626.  
  627.   switch (*Option_String)
  628.   {
  629.     case '?':
  630.  
  631.       if (Option_String[1] == '\0')
  632.       {
  633.         Usage(0, TRUE);
  634.       }
  635.       else
  636.       {
  637.         sscanf (&Option_String[1], "%d", &i);
  638.  
  639.         if ((i >= 0) && (i <= MAX_HELP_PAGE))
  640.         {
  641.           Usage(i, TRUE);
  642.         }
  643.         else
  644.         {
  645.           Usage(0, TRUE);
  646.         }
  647.       }
  648.  
  649.       break;
  650.  
  651.     case '@':
  652.  
  653.       Warning(0.0,"The +@ switch no longer supported. Use +GS.\n");
  654.  
  655.       break;
  656.  
  657.     case 'A':
  658.     case 'a':
  659.  
  660.       switch (Option_String[1])
  661.       {
  662.         case 'm':
  663.         case 'M':
  664.  
  665.           switch (Option_String[2])
  666.           {
  667.             case '1':
  668.  
  669.               opts.Tracing_Method = 1;
  670.  
  671.               break;
  672.  
  673.             case '2':
  674.  
  675.               opts.Tracing_Method = 2;
  676.  
  677.               break;
  678.  
  679.             default:
  680.  
  681.               Warning(0.0, "Unknown antialiasing method. Standard method used.\n");
  682.  
  683.               opts.Tracing_Method = 1;
  684.           }
  685.  
  686.           break;
  687.  
  688.         default:
  689.  
  690.           Option_Number = ANTIALIAS;
  691.  
  692.           if (sscanf (&Option_String[1], DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  693.           {
  694.             opts.Antialias_Threshold = floatval;
  695.           }
  696.       }
  697.  
  698.       break;
  699.  
  700.     case 'B':
  701.     case 'b':
  702.  
  703.       process_variable(BUF_SIZE_OP, &Option_String[1]);
  704.  
  705.       if (opts.File_Buffer_Size > 0)
  706.       {
  707.         Option_Number = BUFFERED_OUTPUT;
  708.       }
  709.  
  710.       break;
  711.  
  712.     case 'C':
  713.     case 'c':
  714.  
  715.       Option_Number = CONTINUE_TRACE;
  716.  
  717.       break;
  718.  
  719.     case 'D':
  720.     case 'd':
  721.  
  722.       Option_Number = DISPLAY;
  723.  
  724.       if (Option_String[1] != '\0')
  725.       {
  726.         opts.DisplayFormat = (char)toupper(Option_String[1]);
  727.       }
  728.  
  729.       if (Option_String[1] != '\0' && Option_String[2] != '\0')
  730.       {
  731.         opts.PaletteOption = (char)toupper(Option_String[2]);
  732.       }
  733.  
  734.       break;
  735.  
  736.     case 'E':
  737.     case 'e':
  738.  
  739.       switch (Option_String[1])
  740.       {
  741.         case 'c':
  742.         case 'C':
  743.  
  744.           process_variable(END_COLUMN_OP,&Option_String[2]);
  745.  
  746.           break;
  747.  
  748.         case 'f':
  749.         case 'F':
  750.           if(isdigit(Option_String[2]))
  751.             process_variable(SUBSET_END_FRAME_OP, &Option_String[2]);
  752.           break;
  753.  
  754.         case 'r':
  755.         case 'R':
  756.  
  757.           process_variable(END_ROW_OP,&Option_String[2]);
  758.  
  759.           break;
  760.  
  761.         case 'p': /* Mosaic Preview Grid Size - End */
  762.         case 'P':
  763.  
  764.           process_variable(PREVIEW_E_OP,&Option_String[2]);
  765.  
  766.           break;
  767.  
  768.         default:
  769.  
  770.           process_variable(END_ROW_OP,&Option_String[1]);
  771.       }
  772.  
  773.       break;
  774.  
  775.     case 'F':
  776.     case 'f':
  777.  
  778.       Option_Number = DISKWRITE;
  779.       
  780.       if (Option_String[1] != '\0')
  781.       {
  782.         opts.OutputFormat = (char)tolower(Option_String[1]);
  783.       }
  784.  
  785.       if (sscanf(&Option_String[2], "%d", &opts.OutputQuality) != 1)
  786.       {
  787.         opts.OutputQuality = 8;
  788.       }
  789.  
  790.       break;
  791.  
  792.     /* Console/file redirection, .INI dump option - [SCD 2/95] */
  793.  
  794.     case 'G':
  795.     case 'g':
  796.  
  797.       switch (Option_String[1])
  798.       {
  799.         case 'a':  /* All */
  800.         case 'A':
  801.  
  802.           process_variable(ALL_CONSOLE_OP,Add_Option ? "On" : "Off");
  803.           process_variable(ALL_FILE_OP,&Option_String[2]);
  804.  
  805.           break;
  806.  
  807.         case 'd':  /* DebugInfo */
  808.         case 'D':
  809.  
  810.           process_variable(DEBUG_CONSOLE_OP,Add_Option ? "On" : "Off");
  811.           process_variable(DEBUG_FILE_OP,&Option_String[2]);
  812.  
  813.           break;
  814.  
  815.         case 'f':  /* Fatal */
  816.         case 'F':
  817.  
  818.           process_variable(FATAL_CONSOLE_OP,Add_Option ? "On" : "Off");
  819.           process_variable(FATAL_FILE_OP,&Option_String[2]);
  820.  
  821.           break;
  822.  
  823.         case 'i':  /* Create .INI containing all settings */
  824.         case 'I':
  825.  
  826.           process_variable(CREATE_INI_OP,&Option_String[2]);
  827.  
  828.           break;
  829.  
  830.         case 'r':  /* RenderInfo */
  831.         case 'R':
  832.  
  833.           process_variable(RENDER_CONSOLE_OP,Add_Option ? "On" : "Off");
  834.           process_variable(RENDER_FILE_OP,&Option_String[2]);
  835.  
  836.           break;
  837.  
  838.         case 's':  /* Statistics */
  839.         case 'S':
  840.  
  841.           process_variable(STATISTIC_CONSOLE_OP,Add_Option ? "On" : "Off");
  842.           process_variable(STATISTIC_FILE_OP,&Option_String[2]);
  843.  
  844.           break;
  845.  
  846.         case 'w':  /* Warning */
  847.         case 'W':
  848.  
  849.           process_variable(WARNING_CONSOLE_OP,Add_Option ? "On" : "Off");
  850.           process_variable(WARNING_FILE_OP,&Option_String[2]);
  851.  
  852.           break;
  853.  
  854.       }
  855.  
  856.       break;
  857.  
  858.     case 'H':
  859.     case 'h':
  860.  
  861.       if (Help_Available)
  862.       {
  863.         if (Option_String[1] == '\0')
  864.         {
  865.           Usage(0, TRUE);
  866.         }
  867.         else
  868.         {
  869.           sscanf (&Option_String[1], "%d", &Frame.Screen_Height);
  870.  
  871.           if ((Frame.Screen_Height >= 0) &&  (Frame.Screen_Height <= MAX_HELP_PAGE))
  872.           {
  873.             Usage(Frame.Screen_Height, TRUE);
  874.           }
  875.         }
  876.       }
  877.       else
  878.       {
  879.         if (!isdigit (Option_String [1]))
  880.         {
  881.           switch (Option_String [1])
  882.           {
  883.             case 'n':  /* Histogram name */
  884.             case 'N':
  885.                  process_variable(HIST_NAME_OP,&Option_String[2]);
  886.                  break ;
  887.  
  888.             case 's':  /* Histogram size */
  889.             case 'S':
  890.                  process_variable(HIST_SIZE_OP,&Option_String[2]);
  891.                  break ;
  892.  
  893.             case 't':  /* Histogram type */
  894.             case 'T':
  895.                  process_variable(HIST_TYPE_OP,&Option_String[2]);
  896.                  break ;
  897.           }
  898.         }
  899.         else
  900.         {
  901.           sscanf (&Option_String[1], "%d", &Frame.Screen_Height);
  902.         }
  903.       }
  904.       break;
  905.  
  906.     case 'I':
  907.     case 'i':
  908.  
  909.       if (Option_String[1] == '\0')
  910.       {
  911.         inflag = TRUE;
  912.       }
  913.       else
  914.       {
  915.         process_variable(INPUT_FILE_NAME_OP, &Option_String[1]);
  916.       }
  917.  
  918.       break;
  919.  
  920.     case 'J':
  921.     case 'j':
  922.  
  923.       Option_Number = JITTER;
  924.  
  925.       if (sscanf (&Option_String[1], DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  926.       {
  927.         opts.JitterScale = floatval;
  928.       }
  929.  
  930.       if (opts.JitterScale <= 0.0)
  931.       {
  932.         Add_Option = FALSE;
  933.       }
  934.  
  935.       break;
  936.  
  937.     case 'K':
  938.     case 'k':
  939.  
  940.       /* Animation-type clock specification */
  941.       switch(Option_String[1])
  942.       {
  943.         case 'c':
  944.         case 'C':
  945.           Option_Number = CYCLIC_ANIMATION;
  946.           break;
  947.  
  948.         case 'i':
  949.         case 'I':
  950.           process_variable(INITIAL_CLOCK_OP, &Option_String[2]);
  951.           break;
  952.  
  953.         case 'f':
  954.         case 'F':
  955.           /* Animation-type clock specification */
  956.           switch(Option_String[2])
  957.           {
  958.             case 'i':
  959.             case 'I':
  960.               process_variable(INITIAL_FRAME_OP, &Option_String[3]);
  961.               break;
  962.  
  963.             case 'f':
  964.             case 'F':
  965.               process_variable(FINAL_FRAME_OP, &Option_String[3]);
  966.               break;
  967.                
  968.             default:
  969.               process_variable(FINAL_CLOCK_OP, &Option_String[2]);
  970.               break;
  971.  
  972.           }
  973.           break;
  974.  
  975.         default:
  976.           /* Standard clock specification */
  977.           process_variable(CLOCK_OP,&Option_String[1]);
  978.           break;
  979.       }
  980.       break;
  981.  
  982.     case 'L':
  983.     case 'l':
  984.  
  985.       process_variable(LIBRARY_PATH_OP,&Option_String[1]);
  986.  
  987.       break;
  988.  
  989.     case 'M': /* Switch used so other max values can be inserted easily */
  990.     case 'm':
  991.  
  992.       switch (Option_String[1])
  993.       {
  994.         case 's': /* Max Symbols */
  995.         case 'S':
  996.  
  997.           Warning(0.0,"+MS or -MS switch no longer needed.\n");
  998.           break;
  999.  
  1000.         case 'v': /* Max Version */
  1001.         case 'V':
  1002.  
  1003.           sscanf (&Option_String[2], DBL_FORMAT_STRING, &opts.Language_Version);
  1004.  
  1005.           break;
  1006.  
  1007.         case 'b': /* Min Bounded */
  1008.         case 'B':
  1009.  
  1010.           if (sscanf (&Option_String[2], "%ld", &longval) != SCANF_EOF)
  1011.           {
  1012.             opts.BBox_Threshold=longval;
  1013.           }
  1014.  
  1015.           opts.Use_Slabs = Add_Option;
  1016.  
  1017.           break;
  1018.  
  1019.         default:
  1020.  
  1021.           break;
  1022.       }
  1023.  
  1024.       break;
  1025.  
  1026.     /*  "N" option flag is used by networking (multi-processor) options.
  1027.  
  1028.     case 'N':
  1029.     case 'n':
  1030.  
  1031.       break;
  1032.  
  1033.      */
  1034.  
  1035.     case 'O':
  1036.     case 'o':
  1037.  
  1038.       if (Option_String[1] == '\0')
  1039.       {
  1040.         outflag = TRUE;
  1041.       }
  1042.       else
  1043.       {
  1044.         process_variable(OUTPUT_FILE_NAME_OP, &Option_String[1]);
  1045.       }
  1046.  
  1047.       break;
  1048.  
  1049.     case 'P':
  1050.     case 'p':
  1051.  
  1052.       Option_Number = PROMPTEXIT;
  1053.  
  1054.       break;
  1055.  
  1056.     case 'Q':
  1057.     case 'q':
  1058.  
  1059.       switch(Option_String[1])
  1060.       {
  1061.         case 'r':
  1062.         case 'R':
  1063.           Option_Number = RADIOSITY;
  1064.           break;
  1065.         case '0':
  1066.         case '1':
  1067.         case '2':
  1068.         case '3':
  1069.         case '4':
  1070.         case '5':
  1071.         case '6':
  1072.         case '7':
  1073.         case '8':
  1074.         case '9':
  1075.           process_variable(QUALITY_OP,&Option_String[1]);
  1076.           break;
  1077.         default:
  1078.           break;
  1079.       }
  1080.       break;
  1081.  
  1082.     case 'R':
  1083.     case 'r':
  1084.  
  1085.       process_variable(ANTIALIAS_DEPTH_OP,&Option_String[1]);
  1086.  
  1087.       break;
  1088.  
  1089.     case 'S':
  1090.     case 's':
  1091.  
  1092.       switch (Option_String[1])
  1093.       {
  1094.         case 'c':
  1095.         case 'C':
  1096.  
  1097.           process_variable(START_COLUMN_OP,&Option_String[2]);
  1098.  
  1099.           break;
  1100.  
  1101.         case 'r':
  1102.         case 'R':
  1103.  
  1104.           process_variable(START_ROW_OP,&Option_String[2]);
  1105.  
  1106.           break;
  1107.  
  1108.         case 'f':
  1109.         case 'F':
  1110.           process_variable(SUBSET_START_FRAME_OP, &Option_String[2]);
  1111.           break;
  1112.  
  1113.         case 'p': /* Mosaic Preview Grid Size - Start */
  1114.         case 'P':
  1115.  
  1116.           process_variable(PREVIEW_S_OP,&Option_String[2]);
  1117.  
  1118.           break;
  1119.  
  1120.         /* Split unions option. [DB 9/94] */
  1121.  
  1122.         case 'U':
  1123.         case 'u':
  1124.  
  1125.           Option_Number = SPLIT_UNION;
  1126.  
  1127.           break;
  1128.  
  1129.         default:
  1130.  
  1131.           process_variable(START_ROW_OP,&Option_String[1]);
  1132.       }
  1133.  
  1134.       break;
  1135.  
  1136.     /* Read vista/light buffer options. [DB 9/94] */
  1137.  
  1138.     case 'U':
  1139.     case 'u':
  1140.  
  1141.       switch (Option_String[1])
  1142.       {
  1143.         case 'l':
  1144.         case 'L':
  1145.  
  1146.           Option_Number = USE_LIGHT_BUFFER;
  1147.  
  1148.           break;
  1149.  
  1150.         case 'd':
  1151.         case 'D':
  1152.  
  1153.           Option_Number = USE_VISTA_DRAW;
  1154.  
  1155.           break;
  1156.  
  1157.         case 'r':
  1158.         case 'R':
  1159.  
  1160.            Option_Number = REMOVE_BOUNDS;
  1161.  
  1162.            break;
  1163.  
  1164.         case 'v':
  1165.         case 'V':
  1166.  
  1167.           Option_Number = USE_VISTA_BUFFER;
  1168.  
  1169.           break;
  1170.  
  1171.         case 'a':
  1172.         case 'A':
  1173.  
  1174.           Option_Number = OUTPUT_ALPHA;
  1175.  
  1176.           break;
  1177.  
  1178.         case 'f':
  1179.         case 'F':
  1180.  
  1181.           process_variable(FIELD_RENDER_OP, Add_Option ? "True" : "False");
  1182.  
  1183.           break;
  1184.  
  1185.         case 'o':
  1186.         case 'O':
  1187.  
  1188.           process_variable(ODD_FIELD_OP, Add_Option ? "True" : "False");
  1189.  
  1190.           break;
  1191.       }
  1192.  
  1193.       break;
  1194.  
  1195.     case 'V':
  1196.     case 'v':
  1197.  
  1198.       Option_Number = VERBOSE;
  1199.       break;
  1200.  
  1201.     case 'W':
  1202.     case 'w':
  1203.  
  1204.       sscanf (&Option_String[1], "%d", &Frame.Screen_Width);
  1205.  
  1206.       break;
  1207.  
  1208.     case 'X':
  1209.     case 'x':
  1210.  
  1211.       Option_Number = EXITENABLE;
  1212.  
  1213.       sscanf (&Option_String[1], "%d", &Abort_Test_Every);
  1214.  
  1215.       opts.Abort_Test_Counter = Abort_Test_Every;
  1216.  
  1217.       break;
  1218.  
  1219.     default:
  1220.  
  1221.       Warning (0.0,"Invalid option: %s.\n", --Option_String);
  1222.   }
  1223.  
  1224.   if (Option_Number != 0)
  1225.   {
  1226.     if (Add_Option)
  1227.     {
  1228.       opts.Options |= Option_Number;
  1229.     }
  1230.     else
  1231.     {
  1232.       opts.Options &= ~Option_Number;
  1233.     }
  1234.   }
  1235. }
  1236.  
  1237.  
  1238.  
  1239.  
  1240. /*****************************************************************************
  1241. *
  1242. * FUNCTION
  1243. *
  1244. *   process_variable
  1245. *
  1246. * INPUT
  1247. *
  1248. * OUTPUT
  1249. *   
  1250. * RETURNS
  1251. *   
  1252. * AUTHOR
  1253. *
  1254. *   POV-Ray Team
  1255. *   
  1256. * DESCRIPTION
  1257. *
  1258. *   Given a token number representing an option variable and a string
  1259. *   that is the value to set, set one option.  If its just an on/off
  1260. *   switch that takes a boolean value then just set Option_Number and
  1261. *   break.  Otherwise process the value and return. 
  1262. *
  1263. * CHANGES
  1264. *
  1265. *   -
  1266. *
  1267. ******************************************************************************/
  1268.  
  1269. void process_variable(variable,value)
  1270. TOKEN variable;
  1271. char *value;
  1272. {
  1273.   int i;
  1274.   long longval;
  1275.   unsigned int Option_Number = 0;
  1276.   DBL floatval;
  1277.  
  1278.   switch (variable)
  1279.   {
  1280.     case BUF_SIZE_OP:
  1281.       if (sscanf (value, "%d", &opts.File_Buffer_Size) != SCANF_EOF)
  1282.       {
  1283.         opts.File_Buffer_Size *= 1024;
  1284.  
  1285.         if (opts.File_Buffer_Size > MAX_BUFSIZE)
  1286.           opts.File_Buffer_Size = MAX_BUFSIZE;
  1287.  
  1288.         /* If 0 then no buffer, other low values use system default MIN */
  1289.         if ((opts.File_Buffer_Size > 0) && (opts.File_Buffer_Size < BUFSIZ))
  1290.         {
  1291.           opts.File_Buffer_Size = BUFSIZ;
  1292.         }
  1293.         if (opts.File_Buffer_Size <= 0)
  1294.         {
  1295.           opts.Options &= ~BUFFERED_OUTPUT;
  1296.         }
  1297.       }
  1298.       return;
  1299.  
  1300.     case BUFFERED_OUTPUT_OP:
  1301.       Option_Number = BUFFERED_OUTPUT;
  1302.       break;
  1303.  
  1304.     case CONTINUE_OP:
  1305.       Option_Number = CONTINUE_TRACE;
  1306.       break;
  1307.  
  1308.     case DISPLAY_OP:
  1309.       Option_Number = DISPLAY;
  1310.       break;
  1311.  
  1312.     case VIDEO_MODE_OP:
  1313.       opts.DisplayFormat = (char)toupper(value[0]);
  1314.       return;
  1315.  
  1316.     case PALETTE_OP:
  1317.       opts.PaletteOption = (char)toupper(value[0]);
  1318.       return;
  1319.  
  1320.     case VERBOSE_OP:
  1321.       Option_Number = VERBOSE;
  1322.       break;
  1323.  
  1324.     case WIDTH_OP:
  1325.       Frame.Screen_Width = atoi(value);
  1326.       return;
  1327.  
  1328.     case HEIGHT_OP:
  1329.       Frame.Screen_Height = atoi(value);
  1330.       return;
  1331.  
  1332.     case FILE_OUTPUT_OP:
  1333.       Option_Number = DISKWRITE;
  1334.       break;
  1335.  
  1336.     case FILE_OUTPUT_TYPE_OP:
  1337.       opts.OutputFormat = (char)tolower(value[0]);
  1338.       return;
  1339.  
  1340.     case PAUSE_WHEN_DONE_OP:
  1341.       Option_Number = PROMPTEXIT;
  1342.       break;
  1343.  
  1344.     case INPUT_FILE_NAME_OP:
  1345.       if (!strcmp(value, "-") || !strcmp(value, "stdin"))
  1346.       {
  1347.         strcpy (opts.Input_File_Name, "stdin");
  1348.         opts.Options |= FROM_STDIN;
  1349.       }
  1350.       else
  1351.       {
  1352.         strncpy (opts.Input_File_Name, value, FILE_NAME_LENGTH);
  1353.       }
  1354.       return;
  1355.  
  1356.     case OUTPUT_FILE_NAME_OP:
  1357.       if (!strcmp(value, "-") || !strcmp(value, "stdout"))
  1358.       {
  1359.         strcpy (opts.Output_File_Name, "stdout");
  1360.         opts.Options |= TO_STDOUT;
  1361.       }
  1362.       else
  1363.       {
  1364.         strncpy (opts.Output_File_Name, value, FILE_NAME_LENGTH);
  1365.       }
  1366.       return;
  1367.  
  1368.     case ANTIALIAS_OP:
  1369.       Option_Number = ANTIALIAS;
  1370.       break;
  1371.  
  1372.     case ANTIALIAS_THRESH_OP:
  1373.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1374.         opts.Antialias_Threshold = floatval;
  1375.       return;
  1376.  
  1377.     case ANTIALIAS_DEPTH_OP:
  1378.       if (sscanf (value, "%ld", &longval) != SCANF_EOF)
  1379.         opts.AntialiasDepth = longval;
  1380.       if (opts.AntialiasDepth < 1)
  1381.         opts.AntialiasDepth = 1;
  1382.       if (opts.AntialiasDepth > 9)
  1383.         opts.AntialiasDepth = 9;
  1384.       return;
  1385.  
  1386.     case JITTER_OP:
  1387.       Option_Number = JITTER;
  1388.       break;
  1389.  
  1390.     case JITTER_AMOUNT_OP:
  1391.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1392.         opts.JitterScale = floatval;
  1393.       if (opts.JitterScale<=0.0)
  1394.         opts.Options &= ~JITTER;
  1395.       return;
  1396.  
  1397.     case TEST_ABORT_OP:
  1398.       Option_Number = EXITENABLE;
  1399.       break;
  1400.  
  1401.     case TEST_ABORT_COUNT_OP:
  1402.       sscanf (value, "%d", &Abort_Test_Every);
  1403.       opts.Abort_Test_Counter = Abort_Test_Every;
  1404.       break;
  1405.  
  1406.     case LIBRARY_PATH_OP:
  1407.       if (opts.Library_Path_Index >= MAX_LIBRARIES)
  1408.         Error ("Too many library directories specified.");
  1409.       for (i = 0; i < opts.Library_Path_Index; i++)
  1410.         if (strcmp(value,opts.Library_Paths[i])==0) return;
  1411.       opts.Library_Paths[opts.Library_Path_Index] = POV_MALLOC(strlen(value)+1,
  1412.                  "library paths");
  1413.       strcpy (opts.Library_Paths [opts.Library_Path_Index], value);
  1414.       opts.Library_Path_Index++;
  1415.       return;
  1416.  
  1417.     case START_COLUMN_OP:
  1418.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1419.         if(floatval > 0.0 && floatval < 1.0)
  1420.         {
  1421.           opts.First_Column = -1;
  1422.           opts.First_Column_Percent = floatval;
  1423.         }
  1424.         else
  1425.           opts.First_Column = ((int) floatval);
  1426.           /* The above used to have -1 but it messed up Write_INI_File.
  1427.            * Moved -1 fudge to fix_up_rendering_window 
  1428.            */
  1429.       return;
  1430.  
  1431.     case START_ROW_OP:
  1432.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1433.         if(floatval > 0.0 && floatval < 1.0)
  1434.         {
  1435.           opts.First_Line = -1;
  1436.           opts.First_Line_Percent = floatval;
  1437.         }
  1438.         else
  1439.           opts.First_Line = ((int) floatval);
  1440.           /* The above used to have -1 but it messed up Write_INI_File
  1441.           * Moved -1 fudge to fix_up_rendering_window 
  1442.           */
  1443.       return;
  1444.  
  1445.     case END_COLUMN_OP:
  1446.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1447.         if(floatval > 0.0 && floatval <= 1.0)
  1448.         {
  1449.           opts.Last_Column = -1;
  1450.           opts.Last_Column_Percent = floatval;
  1451.         }
  1452.         else
  1453.           opts.Last_Column = (int) floatval;
  1454.       return;
  1455.  
  1456.     case END_ROW_OP:
  1457.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1458.         if(floatval > 0.0 && floatval <= 1.0)
  1459.         {
  1460.           opts.Last_Line = -1;
  1461.           opts.Last_Line_Percent = floatval;
  1462.         }
  1463.         else
  1464.           opts.Last_Line = (int) floatval;
  1465.       return;
  1466.  
  1467.     case VERSION_OP:
  1468.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1469.         opts.Language_Version = floatval;
  1470.       return;
  1471.  
  1472.     case BOUNDING_OP:
  1473.       opts.Use_Slabs = istrue(value);
  1474.       return;
  1475.  
  1476.     case BOUNDING_THRESH_OP:
  1477.       opts.BBox_Threshold = atoi(value);
  1478.       return;
  1479.  
  1480.     case QUALITY_OP:
  1481.       opts.Quality = atoi(value);
  1482.       /* Emit a warning about the "radiosity" quality levels for
  1483.        * now.  We can get rid of this some time in the future.
  1484.        */
  1485.       if ((opts.Quality == 10) || (opts.Quality == 11))
  1486.       {
  1487.          Warning(0.0, "Quality settings 10 and 11 are no longer valid.\n"
  1488.                       "Use +QR if you need radiosity.\n");
  1489.          opts.Quality = 9;
  1490.       }
  1491.       else if ((opts.Quality < 0) || (opts.Quality > 9))
  1492.       {
  1493.          Error("Illegal Quality setting.");
  1494.       }
  1495.       opts.Quality_Flags = Quality_Values[opts.Quality];
  1496.       return;
  1497.  
  1498.     case CLOCK_OP:
  1499.       if(sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1500.       {
  1501.         opts.FrameSeq.Clock_Value = floatval;
  1502.       }
  1503.       return;
  1504.  
  1505.     case INITIAL_FRAME_OP:
  1506.       if(sscanf(value, "%ld", &longval)!=SCANF_EOF)
  1507.       {
  1508.         opts.FrameSeq.InitialFrame=longval;
  1509.       }
  1510.       return;
  1511.  
  1512.     case INITIAL_CLOCK_OP:
  1513.       if(sscanf(value, DBL_FORMAT_STRING, &floatval)!=SCANF_EOF)
  1514.       {
  1515.         opts.FrameSeq.InitialClock=floatval;
  1516.       }
  1517.       return;
  1518.  
  1519.     case FINAL_FRAME_OP:
  1520.       if(sscanf(value, "%ld", &longval)!=SCANF_EOF)
  1521.       {
  1522.         opts.FrameSeq.FinalFrame=longval;
  1523.       }
  1524.       return;
  1525.  
  1526.     case FINAL_CLOCK_OP:
  1527.       if(sscanf(value, DBL_FORMAT_STRING, &floatval)!=SCANF_EOF)
  1528.       {
  1529.         opts.FrameSeq.FinalClock=floatval;
  1530.       }
  1531.       return;
  1532.  
  1533.     case SUBSET_START_FRAME_OP:
  1534.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1535.       {
  1536.         if(floatval > 0.0 && floatval < 1.0)
  1537.           opts.FrameSeq.SubsetStartPercent=floatval;
  1538.         else
  1539.           opts.FrameSeq.SubsetStartFrame=(int)floatval;
  1540.       }
  1541.       return;
  1542.  
  1543.     case SUBSET_END_FRAME_OP:
  1544.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1545.       {
  1546.         if(floatval > 0.0 && floatval < 1.0)
  1547.           opts.FrameSeq.SubsetEndPercent=floatval;
  1548.         else
  1549.           opts.FrameSeq.SubsetEndFrame=(int)floatval;
  1550.       }
  1551.       return;
  1552.  
  1553.     case PREVIEW_S_OP:
  1554.       opts.PreviewGridSize_Start = atoi(value);
  1555.       return;
  1556.  
  1557.     case PREVIEW_E_OP:
  1558.       opts.PreviewGridSize_End = atoi(value);
  1559.       return;
  1560.  
  1561.     case CREATE_INI_OP:
  1562.       strcpy(opts.Ini_Output_File_Name,value);
  1563.       return;
  1564.  
  1565.     case ALL_CONSOLE_OP:
  1566.       Stream_Info[ALL_STREAM].do_console =
  1567.       Stream_Info[WARNING_STREAM].do_console =
  1568.       Stream_Info[STATISTIC_STREAM].do_console =
  1569.       Stream_Info[RENDER_STREAM].do_console = 
  1570.       Stream_Info[FATAL_STREAM].do_console = 
  1571.       Stream_Info[DEBUG_STREAM].do_console = istrue(value);
  1572.       return;
  1573.  
  1574.     case ALL_FILE_OP:
  1575.       Do_Stream_Option(ALL_STREAM,value);
  1576.       return;
  1577.  
  1578.     case DEBUG_CONSOLE_OP:
  1579.       Stream_Info[DEBUG_STREAM].do_console = istrue(value);
  1580.       return;
  1581.  
  1582.     case DEBUG_FILE_OP:
  1583.       Do_Stream_Option(DEBUG_STREAM,value);
  1584.       return;
  1585.  
  1586.     case FATAL_CONSOLE_OP:
  1587.       Stream_Info[FATAL_STREAM].do_console = istrue(value);
  1588.       return;
  1589.  
  1590.     case FATAL_FILE_OP:
  1591.       Do_Stream_Option(FATAL_STREAM,value);
  1592.       return;
  1593.  
  1594.     case RENDER_CONSOLE_OP:
  1595.       Stream_Info[RENDER_STREAM].do_console = istrue(value);
  1596.       return;
  1597.  
  1598.     case RENDER_FILE_OP:
  1599.       Do_Stream_Option(RENDER_STREAM,value);
  1600.       return;
  1601.  
  1602.     case STATISTIC_CONSOLE_OP:
  1603.       Stream_Info[STATISTIC_STREAM].do_console = istrue(value);
  1604.       return;
  1605.  
  1606.     case STATISTIC_FILE_OP:
  1607.       Do_Stream_Option(STATISTIC_STREAM,value);
  1608.       return;
  1609.  
  1610.     case WARNING_CONSOLE_OP:
  1611.       Stream_Info[WARNING_STREAM].do_console = istrue(value);
  1612.       return;
  1613.  
  1614.     case WARNING_FILE_OP:
  1615.       Do_Stream_Option(WARNING_STREAM,value);
  1616.       return;
  1617.  
  1618.     case RAD_SWITCH_OP:
  1619.       Option_Number = RADIOSITY;
  1620.       break;
  1621.  
  1622.     case HIST_SIZE_OP:
  1623.       if (sscanf (value, "%d.%d", &opts.histogram_x, &opts.histogram_y) == SCANF_EOF)
  1624.       {
  1625.         Warning (0.0, "Error occurred scanning histogram grid size '%s'.\n", value) ;
  1626.         opts.histogram_on = FALSE ;
  1627.       }
  1628.       break ;
  1629.  
  1630.     case HIST_TYPE_OP:
  1631. #if PRECISION_TIMER_AVAILABLE
  1632.     {
  1633.       char *def_ext = NULL;
  1634.  
  1635.       switch (*value)
  1636.       {
  1637.         case 'C' :
  1638.         case 'c' :
  1639.              opts.histogram_on = TRUE ;
  1640.              opts.histogram_type = CSV ;
  1641.              def_ext = ".csv";
  1642.              break ;
  1643.         case 'S' :
  1644.         case 's' :
  1645.              opts.histogram_on = TRUE ;
  1646.              opts.histogram_type = SYS ;
  1647.              Histogram_File_Handle = GET_SYS_FILE_HANDLE () ;
  1648.              def_ext = SYS_DEF_EXT;
  1649.              break ;
  1650.         case 'P' :
  1651.         case 'p' :
  1652.              opts.histogram_on = TRUE ;
  1653.              opts.histogram_type = PPM ;
  1654.              Histogram_File_Handle = Get_PPM_File_Handle () ;
  1655.              def_ext = ".ppm";
  1656.              break ;
  1657.         case 'T' :
  1658.         case 't' :
  1659.              opts.histogram_on = TRUE ;
  1660.              opts.histogram_type = TARGA ;
  1661.              Histogram_File_Handle = Get_Targa_File_Handle () ;
  1662.              def_ext = ".tga";
  1663.              break ;
  1664.         case 'n':
  1665.         case 'N':
  1666.              opts.histogram_on = TRUE ;
  1667.              opts.histogram_type = PNG ;
  1668.              Histogram_File_Handle = Get_Png_File_Handle () ;
  1669.              def_ext = ".png";
  1670.              break ;
  1671.         case 'x':
  1672.         case 'X':
  1673.              opts.histogram_on = FALSE ;
  1674.              break ;
  1675.         default :
  1676.              Warning (0.0, "Unknown histogram output type '%c'.\n", *value) ;
  1677.              opts.histogram_on = FALSE ;
  1678.              break ;
  1679.       }
  1680.  
  1681.       /* Process the histogram file name now, if it hasn't
  1682.        * yet been specified, and in case it isn't set later.
  1683.        */
  1684.       if (opts.histogram_on && opts.Histogram_File_Name[0] == '\0')
  1685.       {
  1686.         sprintf(opts.Histogram_File_Name, "histgram%s", def_ext);
  1687.       }
  1688.     }
  1689. #else  /* !PRECISION_TIMER_AVAILABLE */
  1690.       if (*value != 'x' && *value != 'X')
  1691.         Warning(0.0,"Histogram output unavailable in this compile of POV-Ray");
  1692.       opts.histogram_on = FALSE;
  1693. #endif /* PRECISION_TIMER_AVAILABLE */
  1694.       break ;
  1695.  
  1696.     case HIST_NAME_OP:
  1697.       if (opts.histogram_on && value[0] == '\0')
  1698.       {
  1699.         char *def_ext = NULL;
  1700.  
  1701.         switch (opts.histogram_type)
  1702.         {
  1703.           case CSV:   def_ext = ".csv"; break;
  1704.           case TARGA: def_ext = ".tga"; break;
  1705.           case PNG:   def_ext = ".png"; break;
  1706.           case PPM:   def_ext = ".ppm"; break;
  1707.           case SYS:   def_ext = SYS_DEF_EXT; break;
  1708.           case NONE:  def_ext = "";     break;  /* To quiet warnings */
  1709.         }
  1710.  
  1711.         sprintf(opts.Histogram_File_Name, "histgram%s", def_ext);
  1712.       }
  1713.       else
  1714.       {
  1715.         strncpy (opts.Histogram_File_Name, value, FILE_NAME_LENGTH);
  1716.       }
  1717.       break ;
  1718.  
  1719.     case VISTA_BUFFER_OP:
  1720.       Option_Number = USE_VISTA_BUFFER;
  1721.       break;
  1722.  
  1723.     case LIGHT_BUFFER_OP:
  1724.       Option_Number = USE_LIGHT_BUFFER;
  1725.       break;
  1726.  
  1727.     case DRAW_VISTAS_OP:
  1728.       Option_Number = USE_VISTA_DRAW;
  1729.       break;
  1730.  
  1731.     case SPLIT_UNIONS_OP:
  1732.       Option_Number = SPLIT_UNION;
  1733.       break;
  1734.  
  1735.     case REMOVE_BOUNDS_OP:
  1736.       Option_Number = REMOVE_BOUNDS;
  1737.       break;
  1738.  
  1739.     case CYCLIC_ANIMATION_OP:
  1740.       Option_Number = CYCLIC_ANIMATION;
  1741.       break;
  1742.  
  1743.     case PRE_SCENE_CMD_OP:
  1744.       strcpy(opts.Shellouts[PRE_SCENE_SHL].Command, value);
  1745.       break;
  1746.  
  1747.     case PRE_FRAME_CMD_OP:
  1748.       strcpy(opts.Shellouts[PRE_FRAME_SHL].Command, value);
  1749.       break;
  1750.  
  1751.     case POST_FRAME_CMD_OP:
  1752.       strcpy(opts.Shellouts[POST_FRAME_SHL].Command, value);
  1753.       break;
  1754.  
  1755.     case POST_SCENE_CMD_OP:
  1756.       strcpy(opts.Shellouts[POST_SCENE_SHL].Command, value);
  1757.       break;
  1758.  
  1759.     case USER_ABORT_CMD_OP:
  1760.       strcpy(opts.Shellouts[USER_ABORT_SHL].Command, value);
  1761.       break;
  1762.  
  1763.     case FATAL_ERROR_CMD_OP:
  1764.       strcpy(opts.Shellouts[FATAL_SHL].Command, value);
  1765.       break;
  1766.  
  1767.     case PRE_SCENE_RET_OP:
  1768.       Do_Return_Option(PRE_SCENE_SHL, value);
  1769.       break;
  1770.  
  1771.     case PRE_FRAME_RET_OP:
  1772.       Do_Return_Option(PRE_FRAME_SHL, value);
  1773.       break;
  1774.  
  1775.     case POST_FRAME_RET_OP:
  1776.       Do_Return_Option(POST_FRAME_SHL, value);
  1777.       break;
  1778.  
  1779.     case POST_SCENE_RET_OP:
  1780.       Do_Return_Option(POST_SCENE_SHL, value);
  1781.       break;
  1782.  
  1783.     case USER_ABORT_RET_OP:
  1784.       Do_Return_Option(USER_ABORT_SHL, value);
  1785.       break;
  1786.  
  1787.     case FATAL_ERROR_RET_OP:
  1788.       Do_Return_Option(FATAL_SHL, value);
  1789.       break;
  1790.  
  1791.     case OUTPUT_ALPHA_OP:
  1792.       Option_Number = OUTPUT_ALPHA;
  1793.       break;
  1794.  
  1795.     case FIELD_RENDER_OP:
  1796.       opts.FrameSeq.Field_Render_Flag = istrue(value);
  1797.       return;
  1798.  
  1799.     case ODD_FIELD_OP:
  1800.       opts.FrameSeq.Odd_Field_Flag = istrue(value);
  1801.       return;
  1802.  
  1803.     case SAMPLING_METHOD_OP:
  1804.       opts.Tracing_Method = atoi(value);
  1805.       return;
  1806.  
  1807.     case BITS_PER_COLOR_OP:
  1808.     case BITS_PER_COLOUR_OP:
  1809.       opts.OutputQuality = atoi(value);
  1810.       opts.OutputQuality = max(5,  opts.OutputQuality);
  1811.       opts.OutputQuality = min(16, opts.OutputQuality);
  1812.       return;
  1813.  
  1814.     case DISPLAY_GAMMA_OP:
  1815.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1816.       {
  1817.         if (floatval > 0.0)
  1818.           opts.DisplayGamma = floatval;
  1819.       }
  1820.       return;
  1821.  
  1822.     case INCLUDE_INI_OP:
  1823.       if (!parse_ini_file(value))
  1824.       {
  1825.         Error ("Could not open Include_Ini='%s'.\n", value);
  1826.       }
  1827.       return;
  1828.  
  1829.     default:
  1830.       Warning(0.0,"Unimplemented INI '%s'.\n",Option_Variable[variable].Token_Name);
  1831.       return;
  1832.  
  1833.   }
  1834.  
  1835.   if (Option_Number != 0)
  1836.   {
  1837.     if (istrue(value))
  1838.     {
  1839.       opts.Options |= Option_Number;
  1840.     }
  1841.     else
  1842.     {
  1843.       opts.Options &= ~Option_Number;
  1844.     }
  1845.   }
  1846. }
  1847.  
  1848.  
  1849.  
  1850. /*****************************************************************************
  1851. *
  1852. * FUNCTION
  1853. *
  1854. *   istrue
  1855. *
  1856. * INPUT
  1857. *   
  1858. * OUTPUT
  1859. *   
  1860. * RETURNS
  1861. *   
  1862. * AUTHOR
  1863. *
  1864. *   POV-Ray Team
  1865. *   
  1866. * DESCRIPTION
  1867. *
  1868. *   -
  1869. *
  1870. * CHANGES
  1871. *
  1872. *   -
  1873. *
  1874. ******************************************************************************/
  1875.  
  1876. static int matches(v1,v2)
  1877. char *v1, *v2;
  1878. {
  1879.   int i=0;
  1880.   int ans=TRUE;
  1881.   
  1882.   while ((ans) && (v1[i] != '\0') && (v2[i] != '\0'))
  1883.   {
  1884.     ans = ans && (v1[i] == tolower(v2[i]));
  1885.     i++;
  1886.   }
  1887.   
  1888.   return(ans);
  1889. }
  1890.  
  1891. static int istrue(value)
  1892. char *value;
  1893. {
  1894.    return (matches("on",value)  || matches("true",value) || 
  1895.            matches("yes",value) || matches("1",value));
  1896. }
  1897.  
  1898. static int isfalse(value)
  1899. char *value;
  1900. {
  1901.    return (matches("off",value)  || matches("false",value) || 
  1902.            matches("no",value)   || matches("0",value));
  1903. }
  1904.  
  1905.  
  1906. /*****************************************************************************
  1907. *
  1908. * FUNCTION
  1909. *
  1910. *   Write_INI_File
  1911. *
  1912. * INPUT
  1913. *   
  1914. * OUTPUT
  1915. *   
  1916. * RETURNS
  1917. *   
  1918. * AUTHOR
  1919. *
  1920. *   SCD, 2/95
  1921. *   
  1922. * DESCRIPTION
  1923. *
  1924. *   Writes all options to an INI file with the current input filename's name
  1925. *   (by default), or using a specified filename.
  1926. *
  1927. * CHANGES
  1928. *
  1929. *   -
  1930. *
  1931. ******************************************************************************/
  1932.  
  1933. void Write_INI_File()
  1934. {
  1935.   int  op, i;
  1936.   char ini_name[FILE_NAME_LENGTH];
  1937.   FILE *ini_file;
  1938.  
  1939.   if (opts.Ini_Output_File_Name[0]=='\0')
  1940.   {
  1941.     return;
  1942.   }
  1943.  
  1944.   if (isfalse(opts.Ini_Output_File_Name))
  1945.   {
  1946.     return;
  1947.     }
  1948.  
  1949.   Status_Info("\nWriting INI file...");
  1950.  
  1951.   if (istrue(opts.Ini_Output_File_Name))
  1952.       {
  1953.     strcpy(ini_name,opts.Scene_Name);
  1954.     strcat(ini_name,".ini");
  1955.       }
  1956.       else
  1957.       {
  1958.     strcpy(ini_name,opts.Ini_Output_File_Name);
  1959.   }
  1960.  
  1961.   if ((ini_file = fopen(ini_name, WRITE_TEXT_FILE_STRING)) == NULL)
  1962.   {
  1963.     Warning (0.0,"Error opening .INI output file '%s' - no file written.\n",
  1964.                     ini_name);
  1965.  
  1966.     return;
  1967.   }
  1968.  
  1969.   for (op = 0; op < MAX_OPTION; op++)
  1970.   {
  1971.     if (op == LIBRARY_PATH_OP)
  1972.     {
  1973.       for (i = 0; i < opts.Library_Path_Index; i++)
  1974.       {
  1975.         fprintf(ini_file,"%s=%s%s",Option_Variable[op].Token_Name,
  1976.                    get_ini_value(op, i),NEW_LINE_STRING);
  1977.       }
  1978.     }
  1979.     /* So that we don't get both Bits_Per_Color and Bits_Per_Colour in
  1980.      * the INI file. */
  1981.     else if ((op != BITS_PER_COLOUR_OP) && (op != INCLUDE_INI_OP))
  1982.     {
  1983.       fprintf(ini_file,"%s=%s%s",Option_Variable[op].Token_Name,
  1984.                    get_ini_value(op, 0),NEW_LINE_STRING);
  1985.     }
  1986.   }
  1987.  
  1988.   fclose(ini_file);
  1989. }
  1990.  
  1991.  
  1992.  
  1993. /*****************************************************************************
  1994. *
  1995. * FUNCTION
  1996. *
  1997. *   parse_ini_file
  1998. *
  1999. * INPUT
  2000. *   
  2001. * OUTPUT
  2002. *   
  2003. * RETURNS
  2004. *   
  2005. * AUTHOR
  2006. *
  2007. *   POV-Ray Team
  2008. *   
  2009. * DESCRIPTION
  2010. *
  2011. *   Given a file name, open it, parse options from it, close it.
  2012. *   Return 1 if file found, 0 if not found.
  2013. *
  2014. * CHANGES
  2015. *
  2016. *   -
  2017. *
  2018. ******************************************************************************/
  2019.  
  2020. int parse_ini_file(File_Name)
  2021. char *File_Name;
  2022. {
  2023.   char Option_Line[512];
  2024.   char INI_Name[FILE_NAME_LENGTH];
  2025.   char Desired_Section[FILE_NAME_LENGTH];
  2026.   char Current_Section[FILE_NAME_LENGTH];
  2027.   char *source, *dest;
  2028.   FILE *ini_file;
  2029.   int Matched, Never_Matched;
  2030.  
  2031.   Stage=STAGE_INI_FILE;
  2032.   
  2033.   /* File_Name can be of the for "FILE.INI[Section]" where everything
  2034.    * before the '[' is the actual name and "[Section]" is the title of
  2035.    * a section within that file that starts with the [Section] heading.  
  2036.    * Only the specified section of the INI file is processed.  If no
  2037.    * section is specified then only parts of the file without a section
  2038.    * header are processed.
  2039.    */
  2040.    
  2041.   /* Copy the file name part */
  2042.   source=File_Name;
  2043.   dest=INI_Name;
  2044.   while ((*source != '\0') && (*source != '['))
  2045.   {
  2046.     *(dest++) = *(source++);
  2047.   }
  2048.   *dest = '\0';
  2049.  
  2050.   /* Copy the section name part */
  2051.   dest = Desired_Section;
  2052.   while ((*source != '\0') && (*source != ']'))
  2053.   {
  2054.     *(dest++) = *(source++);
  2055.   }
  2056.   *dest = *source;
  2057.   *(++dest)='\0';
  2058.  
  2059.   if ((ini_file = Locate_File(INI_Name, READ_TEXT_FILE_STRING,".ini",".INI",FALSE)) == NULL)
  2060.   {
  2061.     return(FALSE);
  2062.   }
  2063.  
  2064.   *Current_Section='\0';
  2065.   
  2066.   Matched = (*Desired_Section == '\0');
  2067.   Never_Matched=TRUE;
  2068.   
  2069.   while (fgets(Option_Line, 512, ini_file) != NULL)
  2070.   {
  2071.     if (*Option_Line == '[')
  2072.     {
  2073.       source=Option_Line;
  2074.       dest=Current_Section;
  2075.       while ((*source != '\0') && (*source != ']'))
  2076.       {
  2077.         *(dest++) = *(source++);
  2078.       }
  2079.       *dest = *source;
  2080.       *(++dest)='\0';
  2081.       Matched = (pov_stricmp(Current_Section, Desired_Section) == 0);
  2082.       
  2083.     }
  2084.     else
  2085.     {    
  2086.        if (Matched)
  2087.        {
  2088.           parse_option_line(Option_Line);
  2089.           Never_Matched=FALSE;
  2090.        }
  2091.     }
  2092.   }
  2093.  
  2094.   if (Never_Matched)
  2095.   {
  2096.      Warning(0.0,"Never found section %s in file %s.\n",Desired_Section,INI_Name);
  2097.   }
  2098.   
  2099.   fclose(ini_file);
  2100.  
  2101.   return(TRUE);
  2102. }
  2103.  
  2104.  
  2105. /*****************************************************************************
  2106. *
  2107. * FUNCTION
  2108. *
  2109. *   parse_option_line
  2110. *
  2111. * INPUT
  2112. *   
  2113. * OUTPUT
  2114. *   
  2115. * RETURNS
  2116. *   
  2117. * AUTHOR
  2118. *
  2119. *   POV-Ray Team
  2120. *   
  2121. * DESCRIPTION
  2122. *
  2123. *   Given a string containing a line of text, split it into individual
  2124. *   switches or options and then pass them off to be parsed by parse_switch
  2125. *   or process_variable.  This routine is called by parse_ini_file,
  2126. *   by the main with argv[] and by READ_ENV_VAR_????
  2127. *
  2128. * CHANGES
  2129. *
  2130. *   Mar 1996 : Allow ';' in an option, if it is escaped  [AED]
  2131. *
  2132. ******************************************************************************/
  2133.  
  2134. void parse_option_line(Option_Line)
  2135. char *Option_Line;
  2136. {
  2137.   char *source, *dest;
  2138.   char Option_String[512];
  2139.   int i,Found;
  2140.  
  2141.   source =  Option_Line;
  2142.  
  2143.   while (TRUE)
  2144.   {
  2145.     /* skip leading white space */
  2146.     while (((int)*source > 0) && ((int)*source < 33))
  2147.     {
  2148.       source++;
  2149.     }
  2150.  
  2151.     /* Quit when finished or ignore if commented */
  2152.     if ((*source == '\0') || (*source == ';'))
  2153.     {
  2154.       return;
  2155.     }
  2156.     
  2157.     if ((*source == '=') || (*source == '#'))
  2158.     {
  2159.       Error("'=' or '#' must be preceded by a keyword.");
  2160.     }
  2161.  
  2162.     /* Copy everything that is not a space, an equals or a comment 
  2163.        into Option_String 
  2164.     */
  2165.     dest = Option_String;
  2166.     while ((isprint((int)*source)) && 
  2167.            (*source != ' ') && 
  2168.            (*source != '=') && 
  2169.            (*source != '#') && 
  2170.            (*source != ';'))
  2171.     {
  2172.       *(dest++) = *(source++);
  2173.     }
  2174.     *dest = '\0';
  2175.  
  2176.     /* At this point, nearly all options that start with a "-" are
  2177.      * options. However the syntax for the +I and the +O 
  2178.      * command-line switches, allows a space to appear between the 
  2179.      * switch and the name.  For example: "+I MYFILE.POV" is legal.  
  2180.      * Since "-" is a legal input and output filename for stdin or
  2181.      * stdout we must parse this before we try to read other options.
  2182.      * If we encounter a "-" without a following option immediately
  2183.      * after a +I or +O switch, it must mean that.  The flags
  2184.      * inflag and outflag indicate that there was a +I or +O switch
  2185.      * parsed just before this file name.
  2186.      */
  2187.  
  2188.     if (inflag)
  2189.     {
  2190.       inflag = FALSE;
  2191.       if (pov_stricmp(Option_String, "-") == 0 ||
  2192.           pov_stricmp(Option_String, "stdin") == 0)
  2193.       {
  2194.         strcpy (opts.Input_File_Name, "stdin");
  2195.         opts.Options |= FROM_STDIN;
  2196.         continue;
  2197.       }
  2198.       else if ((*Option_String != '+') && (*Option_String != '-'))
  2199.       {
  2200.         strncpy (opts.Input_File_Name, Option_String, FILE_NAME_LENGTH);
  2201.         continue;
  2202.       }
  2203.     }
  2204.  
  2205.     if (outflag)
  2206.     {
  2207.       outflag = FALSE;
  2208.       if (pov_stricmp(Option_String, "-") == 0 ||
  2209.           pov_stricmp(Option_String, "stdout") == 0)
  2210.       {
  2211.         strcpy (opts.Output_File_Name, "stdout");
  2212.         opts.Options |= TO_STDOUT;
  2213.         continue;
  2214.       }
  2215.       else if ((*Option_String != '+') && (*Option_String != '-'))
  2216.       {
  2217.         strncpy (opts.Output_File_Name, Option_String, FILE_NAME_LENGTH);
  2218.         continue;
  2219.       }
  2220.     }
  2221.     
  2222.     /* If its a +/- style switch then just do it */
  2223.     if ((*Option_String == '+') || (*Option_String == '-'))
  2224.     {
  2225.       parse_switch(Option_String);
  2226.       continue;
  2227.     }
  2228.  
  2229.     /* Now search the Option_Variables to see if we find a match */
  2230.  
  2231.     Found=-1;
  2232.     for (i = 0 ; i < MAX_OPTION; i++)
  2233.     {
  2234.       if (pov_stricmp(Option_Variable[i].Token_Name, Option_String) == 0)
  2235.       {
  2236.         Found=Option_Variable[i].Token_Number;
  2237.         break;
  2238.       }
  2239.     }
  2240.     
  2241.     if (Found < 0)
  2242.     {
  2243.       /* When an option string does not begin with a '+' or '-', and
  2244.        * is not in the list of valid keywords, then it is assumed to 
  2245.        * be a file name.  Any file names that appear at this point are
  2246.        * .INI/.DEF files to be parsed, or it is an error.
  2247.        */
  2248.        
  2249.       if (++Number_Of_Files > MAX_NESTED_INI)
  2250.       {
  2251.         Error ("Bad option syntax or too many nested .INI/.DEF files.");
  2252.       }
  2253.  
  2254.       if (!parse_ini_file(Option_String))
  2255.       {
  2256.         Error ("Bad option syntax or error opening .INI/.DEF file '%s'.\n", Option_String);
  2257.       }
  2258.       continue;
  2259.     }
  2260.     
  2261.     /* If we make it this far, then it must be an .INI-style setting with
  2262.      * the keyword already verified in "Found".  We now need to verify that
  2263.      * an equals sign follows.  
  2264.      */
  2265.  
  2266.     /* skip white space */
  2267.     while (((int)*source > 0) && ((int)*source < 33))
  2268.     {
  2269.       source++;
  2270.     }
  2271.     
  2272.     if ((*source != '=') && (*source != '#'))
  2273.     {
  2274.       Error("Missing '=' or '#' after %s in option.",Option_String);
  2275.     }
  2276.     
  2277.     source++;
  2278.  
  2279.     /* Now the entire rest of Option_Line up to but excluding a comment, 
  2280.      * becomes the variable part of the option. 
  2281.      */
  2282.  
  2283.     /* skip white space */
  2284.     while (((int)*source > 0) && ((int)*source < 33))
  2285.     {
  2286.       source++;
  2287.     }
  2288.     
  2289.     dest=source;
  2290.     
  2291.     /* Cut off comments and any unprintable characters */
  2292.     while (*source != '\0') 
  2293.     {
  2294.        /* If the comment character is escaped, pass it through */
  2295.        if ((*source == '\\') && (*(source + 1) == ';'))
  2296.        {
  2297.          *source = ';';
  2298.          source++;
  2299.          *source = ' ';
  2300.          source++;
  2301.        }
  2302.        else if ((*source == ';') || (! isprint((int)*source) ) )
  2303.        {
  2304.          *source = '\0';
  2305.        }
  2306.        else
  2307.        {
  2308.          source++;
  2309.        }
  2310.     }
  2311.     process_variable(Found, dest);
  2312.     return;
  2313.   }
  2314. }
  2315.  
  2316.  
  2317.  
  2318. /*****************************************************************************
  2319. *
  2320. * FUNCTION
  2321. *
  2322. * INPUT
  2323. *   
  2324. * OUTPUT
  2325. *   
  2326. * RETURNS
  2327. *   
  2328. * AUTHOR
  2329. *   
  2330. * DESCRIPTION
  2331. *
  2332. * CHANGES
  2333. *
  2334. ******************************************************************************/
  2335.  
  2336. void Do_Stream_Option (i, value)
  2337. int i;
  2338. char *value;
  2339. {
  2340.   if (value==NULL)
  2341.   {
  2342.     return;
  2343.   }
  2344.  
  2345.   if (*value == '\0')
  2346.   {
  2347.     return;
  2348.   }
  2349.  
  2350.   if (Stream_Info[i].name != NULL)
  2351.   {
  2352.     POV_FREE(Stream_Info[i].name);
  2353.  
  2354.     Stream_Info[i].name = NULL;
  2355.   }
  2356.  
  2357.   if (istrue(value))
  2358.   {
  2359.     Stream_Info[i].name = POV_MALLOC(strlen(DefaultFile[i])+1, "stream name");
  2360.  
  2361.     strcpy(Stream_Info[i].name, DefaultFile[i]);
  2362.   }
  2363.   else
  2364.   {
  2365.     if (isfalse(value))
  2366.     {
  2367.       return;
  2368.     }
  2369.  
  2370.     Stream_Info[i].name = POV_MALLOC(strlen(value)+1, "stream name");
  2371.  
  2372.     strcpy(Stream_Info[i].name, value);
  2373.  }
  2374. }
  2375.  
  2376.  
  2377.  
  2378. /*****************************************************************************
  2379. *
  2380. * FUNCTION
  2381. *
  2382. * INPUT
  2383. *   
  2384. * OUTPUT
  2385. *   
  2386. * RETURNS
  2387. *   
  2388. * AUTHOR
  2389. *   
  2390. * DESCRIPTION
  2391. *
  2392. * CHANGES
  2393. *
  2394. ******************************************************************************/
  2395.  
  2396. void Do_Return_Option (Type, value)
  2397. SHELLTYPE Type;
  2398. char *value;
  2399. {
  2400.    char *s;
  2401.    
  2402.    SHELLDATA *Shell=&(opts.Shellouts[Type]);
  2403.    
  2404.    Shell->Inverse=FALSE;
  2405.    Shell->Ret=IGNORE_RET;
  2406.    
  2407.    if (value==NULL)
  2408.      return;
  2409.      
  2410.    if (*value=='\0')
  2411.      return;
  2412.      
  2413.    if ((*value=='-') || (*value=='!'))
  2414.    {
  2415.       Shell->Inverse=TRUE;
  2416.       value++;
  2417.    }
  2418.  
  2419.    if (*value=='\0')
  2420.      return;
  2421.  
  2422.    if ((s=strchr(ret_string,toupper(*value))) == NULL)
  2423.    {
  2424.      Warning(0.0,"Bad value in shellout return '%c'. Only '%s' are allowed.\n",*value,ret_string);
  2425.      Shell->Ret = IGNORE_RET;
  2426.    }
  2427.    else
  2428.    {
  2429.      Shell->Ret = (SHELLRET)(s-ret_string);
  2430.    }
  2431. }
  2432.